JavaScript30
第六天要學習的是利用 fetch 串接 API,並利用新的事件 input 抓取使用者輸入的文字,再使用 正則表達式 篩選出 Data 中哪些地區有符合輸入字串
Github 檔案位置:06 - Type Ahead
網頁一開始的樣子如下
可以先去看看 最後的成品 如下
將程式的要求拆分步驟後,我們需要做的事情如下
應用前幾天學到的東西,不一樣的是這次用了 input 事件 偵測輸入
function displayMatches() {
console.log(this.value) // 確認什麼時候會觸發事件
}
const searchInput = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');
searchInput.addEventListener('input', displayMatches);
在這裡我們利用了 fetch 去串接 API,再利用 json() 將 JSON 檔解析為 JS 物件,並利用 解構賦值 將 Data 傳至我們的 List 中
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
const cities = [];
fetch(endpoint)
.then(item => item.json())
.then(data => cities.push(...data));
console.log(cities);
在這裡我們用到了之前剛學的 filter,不同的是這次用了 正則表達式 和 match 做搭配
new RegExp
會幫助我們建立一個正則表達式的物件,其中 gi
是參數,g
的意思是全域搜尋,i
則是不區分大小寫
match()
會依造我們設立的規則去搜尋 Data,如果存在就會回傳 true
function findMatches(wordToMatch, cities) {
return cities.filter(place => {
// g:全域搜尋
// i:不分大小寫
const regex = new RegExp(wordToMatch, 'gi');
return place.city.match(regex) || place.state.match(regex);
})
}
在這裡可以利用偷懶的方式直接使用 toLocaleString() 函數
function numberWithCommas(x) {
// 由於 x 為字串,要先 * 1 轉型為數字
return (x * 1).toLocaleString();
}
然後我們要學習的是正則表達式的應用
成品如下,replace 做的事情是將正則表達式找到的地方替換為 ,
function numberWithCommas(x) {
// 由於 x 為字串,要先 * 1 轉型為數字
// return (x * 1).toLocaleString();
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
統整完資訊之後,我們將所有資訊包進 HTML 語法的字串中,並以 suggestions.innerHTML
渲染進網頁中
const html = matchArray.map(place => {
const regex = new RegExp(this.value, 'gi');
const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`); // 在符合正則表達式的字上加上選取框
const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`); // 在符合正則表達式的字上加上選取框
return `
<li>
<span class="name">${cityName}, ${stateName}</span>
<span class="population">${numberWithCommas(place.population)}</span>
</li>
`;
}).join('');
suggestions.innerHTML = html;
}
const endpoint = 'https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json';
const cities = [];
fetch(endpoint)
.then(item => item.json())
.then(data => cities.push(...data));
console.log(cities);
function findMatches(wordToMatch, cities) {
return cities.filter(place => {
// g:全域搜尋
// i:不分大小寫
const regex = new RegExp(wordToMatch, 'gi');
return place.city.match(regex) || place.state.match(regex);
})
}
function numberWithCommas(x) {
// 由於 x 為字串,要先 * 1 轉型為數字
// return (x * 1).toLocaleString();
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function displayMatches() {
//console.log(this.value) // 確認什麼時候會觸發事件
const matchArray = findMatches(this.value, cities);
//console.log(matchArray); // 確認正則表達式結果正確
const html = matchArray.map(place => {
const regex = new RegExp(this.value, 'gi');
const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`); // 在符合正則表達式的字上加上選取框
const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`); // 在符合正則表達式的字上加上選取框
return `
<li>
<span class="name">${cityName}, ${stateName}</span>
<span class="population">${numberWithCommas(place.population)}</span>
</li>
`;
}).join('');
suggestions.innerHTML = html;
}
const searchInput = document.querySelector('.search');
const suggestions = document.querySelector('.suggestions');
searchInput.addEventListener('input', displayMatches);
以上是第六天的製作紀錄,如有錯誤或不足的地方還請多多指教 >.<
[ Alex 宅幹嘛 ] 深入淺出 Javascript30 快速導覽Day 6:Type Ahead
Ajax Type Ahead with fetch() - #JavaScript30 6/30
MDN Web Docs